package auth

import (
	"com.lh.basic.service/config"
	"com.lh.basic.service/lib/crypto"
	"com.lh.basic.service/lib/files"
	"com.lh.basic.service/lib/tools"
	"com.lh.basic.service/pb/auth"
	"com.lh.data.data/lib/cockroach"
	"com.lh.data.data/lib/redis"
	"com.lh.mail.service/pb/mailbox"
	"context"
	"errors"
	"fmt"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/types/known/durationpb"
	"net/url"
	"strconv"
	"strings"
	"time"
)

func (a *Auth) GetForget(ctx context.Context, req *auth.ForgetRequest) (*auth.NoResponse, error) {
	db, err := cockroach.GetDB(ctx)
	if err != nil {
		return nil, err
	}
	code := req.GetCode()
	userInfo := &auth.UserForget{}
	list := db.GetEmptyList(userInfo)
	sql := fmt.Sprintf("SELECT %s FROM users.list WHERE name = $1 AND code = $2 AND email = $3", strings.Join(list, ", "))
	var value string
	switch v := code.(type) {
	case *auth.ForgetRequest_Ucode:
		value = v.Ucode
		break
	case *auth.ForgetRequest_Hkcode:
		value = v.Hkcode
		break
	case *auth.ForgetRequest_Twcode:
		value = v.Twcode
		break
	}
	err = db.Pool.QueryRow(db.GetCtx(), sql, req.GetUsername(), value, req.GetEmail()).Scan(&userInfo.Id, &userInfo.Name, &userInfo.Code, &userInfo.Email)
	if err != nil {
		return nil, errors.New("用户信息错误，请检查")
	}
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, errors.New("获取header信息失败")
	}
	sid := md.Get("sid")
	if len(sid) == 0 {
		return nil, errors.New("请刷新浏览器再试")
	}
	red := redis.Init()
	val, err := red.GetHRows(fmt.Sprintf("code_%s:1", sid[0]), "code", "isType")
	if err != nil {
		return nil, err
	}
	if tools.IsNil(val[0]) && tools.IsNil(val[1]) && crypto.Same(val[0].(string), req.GetCoding()) && crypto.Same(val[1].(string), strconv.FormatUint(uint64(req.GetIsType()), 10)) {
		cry := crypto.Init()
		id := cry.RangeUnix()
		if err != nil {
			return nil, err
		}
		token, err := tools.GetToken(&auth.GTokenConfig{
			Sid:      id,
			Duration: durationpb.New(time.Minute * 45),
		})
		if err != nil {
			return nil, err
		}
		if err = red.SetHRow(redis.HConfig{
			Key:      fmt.Sprintf("code_%s:2", id),
			Duration: time.Minute * 15,
			HList:    []interface{}{"id", id, "token", token, "uid", userInfo.Id},
		}); err != nil {
			return nil, err
		}
		search := fmt.Sprintf("sid=%s&uuid=%s&name=%s&email=%s&token=%s", id, cry.Id.String(), userInfo.Name, userInfo.Email, *token)
		search = url.QueryEscape(search)
		serve := config.GetServe("lh_web")
		uri := fmt.Sprintf("%s/register/reset/password?%s", serve.Origin, search)
		file := files.Init()
		data := mailbox.SendRequest{
			Sender:    "allkic@163.com",
			Recipient: []string{req.GetEmail()},
			Subject:   "重置密码",
			IsHtml:    true,
		}
		html, err := file.GetMailHtml("com.lh.basic.service", "reset_password.html", map[string]string{
			"title":    data.GetSubject(),
			"duration": "15分钟",
			"name":     userInfo.Name,
			"uri":      uri,
		})
		data.Body = &html
		if err != nil {
			return nil, err
		}
		conn, err := tools.Proxy("mail")
		if err != nil {
			return nil, err
		}
		mail := mailbox.NewMailboxServiceClient(conn)
		_, err = mail.SendMail(ctx, &data)
		return &auth.NoResponse{
			Code:    200,
			Message: "重置密码链接已发送邮箱，请注意查收！",
			Status:  "ok",
		}, err
	} else {
		return nil, errors.New("您的验证码错误，请检查是否正确")
	}
}

func (a *Auth) Sign(ctx context.Context, req *auth.SignRequest) (*auth.NoResponse, error) {
	return &auth.NoResponse{}, nil
}
